package com.test.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Component
public class JwtUtils {
    @Autowired
    StringRedisTemplate redisTemplate;

    private static final String SIGNATURE = "HugoYu";

    public String CreateToken(Map<String,String> map){
        JWTCreator.Builder builder = JWT.create();
        map.forEach(builder::withClaim);
        builder.withJWTId(UUID.randomUUID().toString());
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.SECOND,60*60*24*7);
        builder.withExpiresAt(instance.getTime());
        return builder.sign(Algorithm.HMAC256(SIGNATURE));
    }
    public DecodedJWT getDecodedJWT(String token){
        try {
            DecodedJWT verify = JWT.require(Algorithm.HMAC256(SIGNATURE)).build().verify(token);
            if(redisTemplate.hasKey(Const.JWT_KEY+verify.getId())) return null;
            return verify;
        }catch (JWTVerificationException e){
            return null;
        }
    }
    public UserDetails toUserDetails(DecodedJWT jwt){
        Map<String, Claim> claims = jwt.getClaims();
        return User
                .withUsername(claims.get("username").asString())
                .password("***")
                .roles(claims.get("rid").asString())
                .build();
    }
    public boolean DeleteJwt(String token){
        DecodedJWT decodedJWT = getDecodedJWT(token);
        if (decodedJWT != null){
            String id = decodedJWT.getId();
            return RedisJwt(id,decodedJWT.getExpiresAt());
        }else return false;
    }
    private boolean RedisJwt(String id, Date time){
        if (redisTemplate.hasKey(Const.JWT_KEY+id)) return false;
        Date now = new Date();
        long time1 = Math.max(time.getTime() - now.getTime() , 0);
        redisTemplate.opsForValue().set(Const.JWT_KEY+id,"",time1, TimeUnit.MILLISECONDS);
        return true;
    }
}
